Friday, 22 June 2007

C# 3.0: Implicitly typed local variables and implicitly typed arrays

We are working on full C# 3.0 support for the Mono gmcs compiler and today I am pleased to announce full support of implicitly typed local variables and implicitly typed arrays.

Implicitly typed local variables

Those who have never heard about implicitly typed local variables maybe noticed new C# 3.0 keyword called `var'. However, the var is not a real keyword; it is what I would call transparent keyword. It behaves like keyword but only if there is no collision with a type of the same name. The rationale behind this is obvious, to make migration to new version as smooth as possible. Therefore, if your existing code uses type called var, don't worry, it will still compile in the same way as it did with the previous version of C# compilers.

As the name says one can use var to implicitly type local variable as shows the following example.

using System;
class ImplicitlyTypedLocalVariables
{
public static void Main ()
{
var max = 10;
for (var i = 0; i < max; ++i)
{
Console.WriteLine (i);
}

var values = new string[] { "a", "b", "c" };
foreach (var s in values)
{
Console.WriteLine (s);
}
}
}

Everywhere var keyword is used, the compiler tries to infer the variable type based on a type of variable initializer. This limits implicitly typed local variables to be used only in a local variable declaration, for each, for, or using statements.
Also as the name says, implicitly typed local variable, you cannot use var for field declaration or constant variables, therefore following declarations will both produce a compiler error.

class Errors
{
var i = 0;
public static void Main ()
{
const var c = 2;
}
}

I am not sure why there are such limitations but I am probably missing something.

Implicitly typed arrays

Implicitly typed arrays are another new C# 3.0 feature probably not as well knows as the var keyword but it can be also useful.

class ImplicitlyTypedArrays
{
public static void Main ()
{
var a1 = new[] {"a", null, "b" };
var a2 = new[] { -1, 0, 2.0 };
var a3 = new[,] { { "a" }, { "b" } };
}
}

Interesting, C#, statically typed language and I cannot see any type whatsoever. How does it work then? It is not that hard to guess, as many other new C# 3.0 features also this one uses type inference. So, if it is possible the compiler tries to infer an array type based on common type (implicit conversion has to exist) of all elements in the array initializer otherwise a compiler error is issued and you have to specify type explicitly. The current draft of C# specification does not mention anything about implicitly typed multi-dimensional arrays. However, the latest Microsoft compiler supports implicitly typed multi-dimensional arrays with the syntax similar to an explicitly typed array. Although they are supported, hard to say whether it is a bug or a feature with required comma syntax.

39 comments:

asbjornu said...

Cool! What I haven't quite got myself to understand yet though, is the need for the "var" keyword. Isn't is just superfluous syntactical sugar? I mean, couldn't the compiler infer the type from the following statement just as well without the var keyword: "max = 10;"?

Marek Safar said...

We can only guess. My guess would be that they wanted future-ready solution. So, instead of changing whole grammar (for, foreach, using, local variable) to use different pattern they just introduced a placeholder.

I can imagine that something like this can be supported in the future.


var Foo (int i)
{
  return 1;
}

Anonymous said...

This is to support LINQ. If you look at LINQ in detail, you would see that supporting it would be a pain without the 'var' functionality.

The short description is that LINQ allows complex anonymous types to be created (based on query parameters) and without the var support you would need to go and first manually define a new class for each possible object that LINQ returns. The var support allows this complexity to be handled by the compiler, and still be 100% type safe.

So while it is not required for everyday (non-LINQ) programming, it is still nice to type:

Note: I don't know how to place angle brackets in the code sample below without the html parser giving me an error, so I used square brackets instead ('[]'). Replace all of the square brackets with angle brackets.

var fooBarDict = new Dictionary[SomeFancyClassFoo, SomeFancyClassBar]();

...instead of...

Dictionary[SomeFancyClassFoo, SomeFancyClassBar]() foobarDict = new Dictionary[SomeFancyClassFoo, SomeFancyClassBar]();

Both are equally type safe, as both versions of fooBarDict are the exact same type.

Timothy Parez said...

Doesn't this take us back a few years and doesn't it allow for lazy programming....

It's like PHP all over again... or is there a good reason, and won't it be abused ?

Anonymous said...

It is not about being lazy, it is about removing redundancy (why do I need to type the variable type twice if the compiler knows exactly what I meant). It is about spending less time on things that can be taken care of automatically, leaving me more time to spend on the real problem I am trying to solve. The same way the GC allowed me to stop spending large amounts of time hunting for memory leaks.

It is also about reducing the amount of bugs being generated. For instance, in the case of LINQ, if I first had to go and manually create every class a LINQ query returns, the possibility of getting something wrong is larger than if I just let the compiler take care of redundant, anonymous types automatically.

I am not a SQL programmer, so I was interested in what the big buzz about LINQ was all about. After reading some details about what it does and how it works, the 'var' support makes sense, and it is clear that it will cut down dramatically on time hunting for bugs and maintenance of code every time one little parameter changes on a LINQ query (somewhat similar to generics in some ways, in that the compiler generates the inferred code).

Also, I am not sure how you can "abuse" this functionality. It is not like this is a variant or a union or something nasty like that. The only thing it will do is make code less cluttered. Can you give an example of how this can be abused?

Marek Safar said...

I am fully aware that the functionality was introduced to support LINQ.

However, my comment was about why to have syntax like

var i = 0;

when we can simply write

i = 0;

Anonymous said...

I think your example is taking it too far because it might be your intention to change an existing variable, but you accidentally mistype the name.

For example, instead of giving you a warning that "querryResult" does not exist (the real name is "queryResult"), it silently creates a new local variable for you. That would probably be relatively obvious on variables with simple names but I have mistyped variables many times before and the compiler error saved me. I have no idea what would have happened if the compiler instead every time silently created the variable I mistyped and in the end I never changed the original variable, which was my real intent.

With the "var" functionality this is not a problem because I am clearly telling the compiler I want to create a brand new variable.

The advantage is that I don't have to figure out what the type needs to be, because the compiler has everything it needs to figure it out by itself, and create the correct, strongly typed variable.

Now of course if I do want to create a variable of a different type, nothing prevents me from still doing it the explicit way, like:

object obj = new MyFancyClass();

I can see why many people would dislike the "var" functionality because things like variants, unions and void pointers have left a bad taste in our mouth, and also because many people think "var" is really just of type "object", when in fact it is the fully qualified type you are creating. After the declaring line it behaves exactly as if you explicitly specified the type, so how this can be abused is not clear to me.

Anonymous said...

> I am not sure why there are such
> limitations but I am probably
> missing something.

Unlike local "vars", whose type can be deterministically inferred,
if non-const "var" fields were allowed, their underlying type has to be "object",
because they can be assigned more the once.

Thus "var" fields were equivalent to plain "object" fields.
I think that MS has chosen not to obfuscate this equivalence with the new "var" keyword.

knocte said...

>> I am not sure why there are such
>> limitations but I am probably
>> missing something.

>Unlike local "vars", whose type can be
>deterministically inferred,
>if non-const "var" fields were allowed,
>their underlying type has to be
>"object", because they can be assigned
>more the once.
>
>Thus "var" fields were equivalent to
>plain "object" fields.
>I think that MS has chosen not to
>obfuscate this equivalence with the new
>"var" keyword.

And also because that would really convert the use of var into the "type-dinamicalization" of C#. MS didn't want to make C# no longer statically typed I suppose.

Marek Safar said...

>> I am not sure why there are such
>> limitations but I am probably
>> missing something.

>Unlike local "vars", whose type can be >deterministically inferred,
>if non-const "var" fields were allowed, >their underlying type has to be "object",
>because they can be assigned more the >once.

I am not sure whether I got your point.
Why should they be an object ? There is technically no difference between assigned local and assigned type variable, assigned type variable becomes assigned local variable automatically by compiler anyway.

I personally have one or two tips but nothing what I would say. Yeah, that's it.

What about local constants ?

Anonymous said...

Marek, look at this sample:

class T
{
var i;
void A ()
{
i = 42;
}
void B ()
{
i = "Test";
A ();
// i is not a string anymore
}
}

Which type has the field T.i in this case? It can't be something else than an object, IMO.

Even if the compiler were able to infer the type within a certain block, there could be still side effects, especially when visibility attributes (public, protected) were allowed.

Marek Safar said...

Yes, that's what I thought.

However, you sample ignores the fact that implicit type initializers have to have an initializer otherwise it is obviously different discussion. This is also what my sample shows.

Zoe said...

I like the way that Boo works. Everything is implicitly typed as long as you assign the variable when you create it (for obvious reasons). So the only times you need to specify the type are when you define a variable without assigning it, it's ambiguous (and won't compile) or it chooses something other than what you wanted (usually a boxing issue).

The approach is much better, I think. I have not done much C/C++ programming, I'm used to more agile, higher-level languages like Perl, Python and Ruby. C# was a jolt because it was so much more verbose but it allowed me to access the extensive power of .Net/Mono. Discovering Boo allowed me to work with all the same .Net stuff but in a much smarter way, my code shrunk anywhere from 10% to 50%.

Compilers are there to do the hard work, unless we all want to write in assembly/CIL O_O GCC can do all sorts of fancy optimizations and whatnot and end up better than hand-tweaked assembly. Why? Because computers are good for that sort of thing. So when the answer is obvious to the computer, why force the programmer to answer what is obvious to everyone?

This is different than dynamically-typed variables like in Python or Ruby, where you can just overwrite variables with new definitions and this leads to confusing bugs. However, Boo supports a pseudo-dynamically-typed class called "duck", which is statically-typed as far as .Net is concerned but actually every time it is used, it's true nature is ascertained. You can even make it the default. This is mainly useful for porting Python/Ruby code.

So, check it out. It is the "wrist-friendly language". Work smarter, not harder.

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

外国為替
ホスト
結婚相談所、結婚情報、結婚紹介
ヘアスタイル
カップリングパーティー
ジュエリー通販
渋谷サロン
ビューティーサロン
アロママッサージ
六本木マッサージ
転職マッサージ
ローン比較マッサージ

Anonymous said...

外国為替
ホスト
結婚相談所、結婚情報、結婚紹介
ヘアスタイル
カップリングパーティー
ジュエリー通販
渋谷サロン
ビューティーサロン
アロママッサージ
六本木マッサージ
転職
ローン比較

Anonymous said...

防丢额外耳蜗杭州装饰公司

Anonymous said...

防丢额外耳蜗杭州装饰公司
家政
杭州酒店装修
杭州店面装修
杭州装修公司

Anonymous said...

pornstar dildos pornstar dildos
jack rabbit vibrators jack rabbit vibrators
vibrating bullets vibrating bullets
strap on dildos for women strap on dildos for women
cock rings cock rings
penis enlargement pumps penis enlargement pumps
pocket pussies pocket pussies
anal sex toys anal sex toys

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

デリヘル東京はデリバリーヘルスの情報です。

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

チャットレディー
チャットレディー

Anonymous said...

ホストクラブ求人

Anonymous said...

ホストクラブ

Anonymous said...

クレジットカード現金化
クレジットカードショッピング枠現金化
ショッピング枠現金化

Anonymous said...

クレジットカード現金化
クレジットカードショッピング枠現金化
ショッピング枠現金化

Anonymous said...

吉原 ソープ今までの吉原にはまったくない、新しい吉原 ソープのお店です。お客様に提供するのは、究極の癒しとリラクゼーション吉原 ソープです。今まで吉原 ソープに縁の無かったお客様のニーズにお応えします。 吉原 ソープ今までの吉原にはまったくない、新しい吉原 ソープのお店です。お客様に提供するのは、究極の癒しとリラクゼーション吉原 ソープです。今まで吉原 ソープに縁の無かったお客様のニーズにお応えします。 吉原 ソープ今までの吉原にはまったくない、新しい吉原 ソープのお店です。お客様に提供するのは、究極の癒しとリラクゼーション吉原 ソープです。今まで吉原 ソープに縁の無かったお客様のニーズにお応えします。

Anonymous said...

精力剤勃起 不全,勃起薬,勃起, 精力剤 勃起機能低下, インポ, 精力剤,カマグラ, 精力剤,MAX, 精力剤 精力剤勃起 不全,勃起薬,勃起, 精力剤 勃起機能低下, インポ, 精力剤,カマグラ, 精力剤,MAX, 精力剤 精力剤勃起 不全,勃起薬,勃起, 精力剤 勃起機能低下, インポ, 精力剤,カマグラ, 精力剤,MAX, 精力剤

Anonymous said...

男性下着 のことならプロパガンダ。他にも男性下着 、ビキニ、男性下着 、トランクスからセクシー系まで男性下着 のことならお任せください。" 男性下着 のことならプロパガンダ。他にも男性下着 、ビキニ、男性下着 、トランクスからセクシー系まで男性下着 のことならお任せください。" 男性下着 のことならプロパガンダ。他にも男性下着 、ビキニ、男性下着 、トランクスからセクシー系まで男性下着 のことならお任せください。"

Anonymous said...

And... It only took until the send poster to fall for that one. Yer so smart.
-

Anonymous said...

Really nice information, thanks for sharing!thanks!
8 ove-weight-two/ _

8

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...

チャットレディー
チャットレディー
チャットレディー
テレフォンレディー
テレフォンレディー
テレフォンレディー

Anonymous said...

高収入 アルバイト
高収入 アルバイト
アパレル 求人
アパレル 派遣
人妻 出会い

Anonymous said...

チャットレディー

Anonymous said...
This comment has been removed by a blog administrator.
Anonymous said...
This comment has been removed by a blog administrator.